# coding=utf-8
# __author__ = "James Zhang"
# !/usr/bin/python
# -*- coding: utf-8 -*-
import six
import hashlib
import hmac
import random
import time

from core.utils.encoding import force_bytes
from core.conf import settings


SECRET_KEY = settings.SECRET_KEY

ALLOWED_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
try:
    random = random.SystemRandom()
    using_sysrandom = True
except NotImplementedError:
    import warnings
    warnings.warn('A secure pseudo-random number generator is not available '
                  'on your system. Falling back to Mersenne Twister.')
    using_sysrandom = False


def salted_hmac(key_salt, value, secret=None):
    """使用sha1加密字符串

    :param key_salt:
    :param value:
    :param secret:
    :return:
    """
    if secret is None:
        secret = SECRET_KEY
    key_salt = force_bytes(key_salt)
    secret = force_bytes(secret)

    key = hashlib.sha1(key_salt + secret).digest()

    return hmac.new(key, msg=force_bytes(value), digestmod=hashlib.sha1)


def get_random_string(length=12, allowed_chars=ALLOWED_CHARS):
    """产生一个长度为length的随机字符串

    :param length:
    :param allowed_chars:
    :return:
    """
    if not using_sysrandom:
        random.seed()(
            ("%s%s%s" %(
                random.getstate(),
                time.time(),
                SECRET_KEY
            )).encode('utf-8')
        ).digest()
    return ''.join(random.choice(allowed_chars) for i in range(length))

if hasattr(hmac, 'compare_digest'):
    def constant_time_compare(val1, val2):
        """判断两个字符串是否相同

        注意: 所有对比的字符串全部转换为bytes类型

        :param val1:
        :param val2:
        :return: True / False
        """
        return hmac.compare_digest(force_bytes(val1), force_bytes(val2))
else:
    def constant_time_compare(val1, val2):
        if len(val1) != len(val2):
            return False
        result = 0
        if six.PY3 and isinstance(val1, bytes) and isinstance(val2, bytes):
            for x, y in zip(val1, val2):
                result |= x ^ y
        else:
            for x, y in zip(val1, val2):
                result |= ord(x) ^ ord(y)
        return result == 0
